/************************************************************************
 * TestEngine/Examples - Automata Identification Engine
 * Copyright (C) 2012-2013 Ali Khalili (khalili_DOT_ir_@SIGN_gmail_DOT_com)
 * **********************************************************************
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License (LGPL) published 
 * by the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version. This program is distributed without any
 * warranty. See the GNU Lesser General Public License for more details. 
 * ***********************************************************************
 * File         :     
 * Description  :     
 * Change log   :     	-Date:  Change
 ************************************************************************/
﻿using System;
using System.Collections.Generic;
using MBT.Modeling;
using SMLib.DataTypes;


namespace TestingApp.Examples
{
    public class ChatModel
    {
        public ChatModel()
        {

        }

        [DomainDef("Clients")]
        public List<int> Clients()
        {
            return allClients;
        }

        #region [login]
        [ActionAttrib.Exec("Login", ActionType.controllable)]
        public void Login([Domain("Clients")] int cid)
        {
            clientStats[cid] = 1;
        }

        [ActionAttrib.Pre("Login")]
        public bool Login_Enabled(int cid)
        {
            return (clientStats[cid] == 0);
        }
        #endregion

        #region [logout]
        [ActionAttrib.Exec("Logout", ActionType.controllable)]
        public void LogOut([Domain("Clients")] int cid)
        {
            clientStats[cid] = 0;
            MessageQueue[cid].Clear();
        }

        [ActionAttrib.Pre("Logout")]
        public bool LogOut_Enabled(int cid)
        {
            return Send_Enabled(cid);
            //return (clientStats[cid] == 1);
        }
        #endregion


        #region [send]
        [ActionAttrib.Exec("Send", ActionType.controllable)]
        public void Send([Domain("Clients")] int sender)
        {
            for (int i = 0; i < NUMBER; i++)
            {
                if (this.clientStats[i] == 1 && i != sender)
                {
                    this.MessageQueue[i].Add(sender);
                }
            }
        }

        [ActionAttrib.Pre("Send")]
        public bool Send_Enabled(int sender)
        {
            if (clientStats[sender] == 0)
                return false;

            for (int i = 0; i < NUMBER; i++)
            {
                if (this.MessageQueue[i].Contains(sender))
                    return false;
            }
            return true;
        }
        #endregion

        #region [recieve]
        [ActionAttrib.Exec("Recieve", ActionType.observable)]
        public void Recieve([Domain("Clients")] int reciever, [Domain("Clients")] int sender)
        {
            MessageQueue[reciever].RemoveAt(0);
        }

        [ActionAttrib.Pre("Recieve")]
        public bool Recieve_Enabled(int reciever, int sender)
        {
			try{
            	return (MessageQueue[reciever].Count > 0 && MessageQueue[reciever][0] == sender);
			}
			catch
			{
				Console.WriteLine("OOOPS!");
				return false;
			}
        }
        #endregion


        public static int NUMBER = 2;

        public EnArray<int> clientStats;

        public EnArray<EnList<int>> MessageQueue;
        public EnList<int> allClients;

        public static object[] Construct()
        {
            ChatModel c = new ChatModel();
            c.clientStats = new EnArray<int>(NUMBER);
            c.allClients = new EnList<int>();
            for (int i = 0; i < NUMBER; i++)
                c.allClients.Add(i);

            c.MessageQueue = new EnArray<EnList<int>>(NUMBER);
            for (int i = 0; i < NUMBER; i++)
            {
                c.clientStats[i] = 0;
                c.MessageQueue[i] = new EnList<int>();
            }
            return new object[] { c };
        }
    }
}
